package org.zoomdev.zoom.common.utils;

import org.zoomdev.zoom.common.exceptions.ZoomException;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

public final class Creators {
    public static Collection newCollection(Class<?> type) {
        if (type.isInterface()) {
            if (List.class.isAssignableFrom(type)) {
                return new ArrayList();
            } else if (Set.class.isAssignableFrom(type)) {
                return new LinkedHashSet();
            } else if (Collection.class.isAssignableFrom(type)) {
                return new ArrayList();
            } else if (Iterable.class.isAssignableFrom(type)) {
                return new ArrayList();
            } else {
                throw new ZoomException("Cannot initialize " + type);
            }
        } else {
            return (Collection) Classes.newInstance(type);
        }
    }
    public static Object newInstance(Constructor constructor, Object... args) {
        try {
            return constructor.newInstance(args);
        } catch (Exception e) {
            throw new ZoomException(e);
        }
    }

    /**
     * 直接初始化一个对象
     *
     * @param type
     * @return
     */
    public static Object newInstance(Class<?> type) {
        // 如果是泛型，那么就new一个对应的出来
        // 如果是array类型，那么就new一个数组
        // new一个普通的
        if (type == null) {
            throw new NullPointerException();
        }

        try {
            return type.newInstance();
        } catch (Throwable e) {
            throw new ZoomException("不能初始化" + type, e);
        }
    }

    public static ParameterizedType listType(Class<?> elementClass) {
        return new ListParameterizedType(elementClass);
    }

    public static ZoomException makeThrow(Throwable e) {
        if (e instanceof InvocationTargetException) {
            return makeThrow(((InvocationTargetException) e).getTargetException());
        }
        if (e instanceof ZoomException) {
            return (ZoomException) e;
        }
        return new ZoomException(e);
    }

    static class ListParameterizedType implements ParameterizedType {

        private final Class<?> elementClass;

        ListParameterizedType(Class<?> elementClass) {
            this.elementClass = elementClass;
        }

        @Override
        public Type[] getActualTypeArguments() {
            return new Type[]{elementClass};
        }

        @Override
        public Type getRawType() {
            return List.class;
        }

        @Override
        public Type getOwnerType() {
            return null;
        }
    }
}
